using System;
using System.Diagnostics;
using System.IO;
using System.Windows.Forms;
using System.Xml;

namespace UselessExplorer
{
    public class Logger
    {

        private static Logger instance;
        public static Logger Instance
        {
            get
            {
                if (instance == null)
                {
                    instance = new Logger();
                }
                return instance;
            }
        }

        public enum LogsCategory
        {
            Debug = 1,
            Exception = 2,
            Message = 3
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="LogsCat"></param>
        /// <param name="ex"></param>
        public void WriteLogs(LogsCategory LogsCat, Exception ex)
        {
            StackTrace st = new StackTrace();
            StackFrame frame = st.GetFrame(2);

            string category = GetLogsCategory(LogsCat);
            string methodName = String.Format("[{0}.{1}]", frame.GetMethod().ReflectedType.FullName, frame.GetMethod().Name);
            string logMessage = String.Format("{0}", ex.Message);
            string stackTrace = String.Format("{0}", ex.StackTrace);
            string date = String.Format("{0} {1}", DateTime.Now.ToLongDateString(), DateTime.Now.ToShortTimeString());

            // Adds the message to the Form Logs for display
            frmTraces.Instance.AddMessage(category, date, methodName, logMessage, stackTrace);

            // Writes the Logs to the XML file
            Write2XML(category, methodName, logMessage, stackTrace, date);
        }

        private string GetLogsCategory(LogsCategory LogsCat)
        {
            switch (Convert.ToInt32(LogsCat))
            {
                case 1:
                    return "DEBUG";
                case 2:
                    return "EXCEPTION";
                case 3:
                    return "MESSAGE";
                default:
                    return "UNKNOWN";
            }
        }


        private void Write2XML(string category, string method, string message, string stackTrace, string date)
        {

            XmlDocument xmldoc;
            string appPath = Application.StartupPath + @"\";
            string fullPath = "ErrorLogs.xml";

            try
            {
                FileStream fs = new FileStream(fullPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
                xmldoc = new XmlDocument();
                xmldoc.Load(fs);

                XmlNode xmlnode = xmldoc.LastChild.LastChild;
                XmlAttributeCollection xmlattr = xmlnode.Attributes;
                int lastErrorId = Convert.ToInt32(xmlattr[0].Value);
                int currentErrorId = ++lastErrorId;


                XmlElement newcatalogentry = xmldoc.CreateElement("Error");
                XmlAttribute newcatalogattr = xmldoc.CreateAttribute("ID");
                newcatalogattr.Value = currentErrorId.ToString();
                newcatalogentry.SetAttributeNode(newcatalogattr);

                XmlElement xmlelem2 = xmldoc.CreateElement("", "Category", "");
                xmlelem2.InnerText = category;
                newcatalogentry.AppendChild(xmlelem2);

                XmlElement xmlelem3 = xmldoc.CreateElement("", "Date", "");
                xmlelem3.InnerText = date;
                newcatalogentry.AppendChild(xmlelem3);

                XmlElement xmlelem4 = xmldoc.CreateElement("", "Method", "");
                xmlelem4.InnerText = method;
                newcatalogentry.AppendChild(xmlelem4);

                XmlElement xmlelem5 = xmldoc.CreateElement("", "Message", "");
                xmlelem5.InnerText = message;
                newcatalogentry.AppendChild(xmlelem5);

                XmlElement xmlelem6 = xmldoc.CreateElement("", "StackTrace", "");
                xmlelem6.InnerText = stackTrace;
                newcatalogentry.AppendChild(xmlelem6);

                xmldoc.DocumentElement.InsertAfter(newcatalogentry, xmldoc.DocumentElement.LastChild);

                FileStream fsxml = new FileStream(fullPath, FileMode.Truncate, FileAccess.Write, FileShare.ReadWrite);
                xmldoc.Save(fsxml);
            }
            catch (FileNotFoundException)
            {
                CreateNewLogFile(category, date, method, message, stackTrace, fullPath);
            }
        }

        private void CreateNewLogFile(string category, string date, string method, string message, string stackTrace, string fileName)
        {
            XmlDocument newLogFile = new XmlDocument();
            XmlNode xmlnode = newLogFile.CreateNode(XmlNodeType.XmlDeclaration, "", "");
            newLogFile.AppendChild(xmlnode);

            XmlElement xmlRootElem = newLogFile.CreateElement("", "Errors", "");
            newLogFile.AppendChild(xmlRootElem);

            XmlElement xmlelem = newLogFile.CreateElement("", "Error", "");
            XmlAttribute xmlattr = newLogFile.CreateAttribute("ID");
            xmlattr.Value = "1";
            xmlelem.SetAttributeNode(xmlattr);
            newLogFile.ChildNodes.Item(1).AppendChild(xmlelem);

            XmlElement xmlelem2 = newLogFile.CreateElement("", "Category", "");
            xmlelem2.InnerText = category;
            xmlelem.AppendChild(xmlelem2);

            XmlElement xmlelem3 = newLogFile.CreateElement("", "Date", "");
            xmlelem2.InnerText = date;
            xmlelem.AppendChild(xmlelem3);

            XmlElement xmlelem4 = newLogFile.CreateElement("", "Method", "");
            xmlelem2.InnerText = method;
            xmlelem.AppendChild(xmlelem4);

            XmlElement xmlelem5 = newLogFile.CreateElement("", "Message", "");
            xmlelem2.InnerText = message;
            xmlelem.AppendChild(xmlelem5);

            XmlElement xmlelem6 = newLogFile.CreateElement("", "StackTrace", "");
            xmlelem2.InnerText = stackTrace;
            xmlelem.AppendChild(xmlelem6);

            newLogFile.Save(fileName);

        }
    }
}
